From: kfraser@ubuntu.eng.hq.xensource.com Date: Tue, 5 Sep 2006 19:20:31 +0000 (-0700) Subject: [XEN] Clean up grant-table pinning logic. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15668^2~8 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https://%22%22/%22http:/www.example.com/cgi/%22https:/%22%22?a=commitdiff_plain;h=ea72eea319dd5a6ddee16ca194b23056b56db15e;p=xen.git [XEN] Clean up grant-table pinning logic. Signed-off-by: Keir Fraser --- diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 95d36fce4e..68e2bf62d7 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -90,11 +90,8 @@ __gnttab_map_grant_ref( unsigned long frame = 0; int rc = GNTST_okay; struct active_grant_entry *act; - - /* Entry details from @rd's shared grant table. */ grant_entry_t *sha; - domid_t sdom; - u16 sflags; + union grant_combo scombo, prev_scombo, new_scombo; /* * We bound the number of times we retry CMPXCHG on memory locations that @@ -175,13 +172,20 @@ __gnttab_map_grant_ref( spin_lock(&rd->grant_table->lock); - sdom = sha->domid; + /* If already pinned, check the active domid and avoid refcnt overflow. */ + if ( act->pin && + ((act->domid != ld->domain_id) || + (act->pin & 0x80808080U) != 0) ) + PIN_FAIL(unlock_out, GNTST_general_error, + "Bad domain (%d != %d), or risk of counter overflow %08x\n", + act->domid, ld->domain_id, act->pin); if ( !act->pin || (!(op->flags & GNTMAP_readonly) && !(act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask))) ) { - sflags = sha->flags; + scombo.shorts.flags = sha->flags; + scombo.shorts.domid = sha->domid; /* * This loop attempts to set the access (reading/writing) flags @@ -191,33 +195,29 @@ __gnttab_map_grant_ref( */ for ( ; ; ) { - union grant_combo scombo, prev_scombo, new_scombo; - - if ( unlikely((sflags & GTF_type_mask) != GTF_permit_access) || - unlikely(sdom != led->domain->domain_id) ) - PIN_FAIL(unlock_out, GNTST_general_error, - "Bad flags (%x) or dom (%d). (NB. expected dom %d)\n", - sflags, sdom, led->domain->domain_id); + /* If not already pinned, check the grant domid and type. */ + if ( !act->pin && + (((scombo.shorts.flags & GTF_type_mask) != + GTF_permit_access) || + (scombo.shorts.domid != ld->domain_id)) ) + PIN_FAIL(unlock_out, GNTST_general_error, + "Bad flags (%x) or dom (%d). (expected dom %d)\n", + scombo.shorts.flags, scombo.shorts.domid, + ld->domain_id); - /* Merge two 16-bit values into a 32-bit combined update. */ - scombo.shorts.flags = sflags; - scombo.shorts.domid = sdom; - new_scombo = scombo; new_scombo.shorts.flags |= GTF_reading; if ( !(op->flags & GNTMAP_readonly) ) { new_scombo.shorts.flags |= GTF_writing; - if ( unlikely(sflags & GTF_readonly) ) + if ( unlikely(scombo.shorts.flags & GTF_readonly) ) PIN_FAIL(unlock_out, GNTST_general_error, "Attempt to write-pin a r/o grant entry.\n"); } prev_scombo.word = cmpxchg((u32 *)&sha->flags, scombo.word, new_scombo.word); - - /* Did the combined update work (did we see what we expected?). */ if ( likely(prev_scombo.word == scombo.word) ) break; @@ -225,24 +225,15 @@ __gnttab_map_grant_ref( PIN_FAIL(unlock_out, GNTST_general_error, "Shared grant entry is unstable.\n"); - /* Didn't see what we expected. Split out the seen flags & dom. */ - sflags = prev_scombo.shorts.flags; - sdom = prev_scombo.shorts.domid; + scombo = prev_scombo; } if ( !act->pin ) { - act->domid = sdom; + act->domid = scombo.shorts.domid; act->frame = gmfn_to_mfn(rd, sha->frame); } } - else if ( unlikely(sdom != ld->domain_id) ) - PIN_FAIL(unlock_out, GNTST_general_error, - "Bad domain (%d). (NB. expected dom %d)\n", - sdom, ld->domain_id); - else if ( (act->pin & 0x80808080U) != 0 ) - PIN_FAIL(unlock_out, ENOSPC, - "Risk of counter overflow %08x\n", act->pin); if ( op->flags & GNTMAP_device_map ) act->pin += (op->flags & GNTMAP_readonly) ? @@ -550,9 +541,7 @@ gnttab_prepare_for_transfer( { struct grant_table *rgt; struct grant_entry *sha; - domid_t sdom; - u16 sflags; - union grant_combo scombo, prev_scombo, tmp_scombo; + union grant_combo scombo, prev_scombo, new_scombo; int retries = 0; if ( unlikely((rgt = rd->grant_table) == NULL) || @@ -567,29 +556,25 @@ gnttab_prepare_for_transfer( sha = &rgt->shared[ref]; - sflags = sha->flags; - sdom = sha->domid; + scombo.shorts.flags = sha->flags; + scombo.shorts.domid = sha->domid; for ( ; ; ) { - if ( unlikely(sflags != GTF_accept_transfer) || - unlikely(sdom != ld->domain_id) ) + if ( unlikely(scombo.shorts.flags != GTF_accept_transfer) || + unlikely(scombo.shorts.domid != ld->domain_id) ) { DPRINTK("Bad flags (%x) or dom (%d). (NB. expected dom %d)\n", - sflags, sdom, ld->domain_id); + scombo.shorts.flags, scombo.shorts.domid, + ld->domain_id); goto fail; } - /* Merge two 16-bit values into a 32-bit combined update. */ - scombo.shorts.flags = sflags; - scombo.shorts.domid = sdom; + new_scombo = scombo; + new_scombo.shorts.flags |= GTF_transfer_committed; - tmp_scombo = scombo; - tmp_scombo.shorts.flags |= GTF_transfer_committed; prev_scombo.word = cmpxchg((u32 *)&sha->flags, - scombo.word, tmp_scombo.word); - - /* Did the combined update work (did we see what we expected?). */ + scombo.word, new_scombo.word); if ( likely(prev_scombo.word == scombo.word) ) break; @@ -599,9 +584,7 @@ gnttab_prepare_for_transfer( goto fail; } - /* Didn't see what we expected. Split out the seen flags & dom. */ - sflags = prev_scombo.shorts.flags; - sdom = prev_scombo.shorts.domid; + scombo = prev_scombo; } spin_unlock(&rgt->lock); @@ -739,16 +722,21 @@ __release_grant_for_copy( gnttab_mark_dirty(rd, r_frame); spin_lock(&rd->grant_table->lock); + if ( readonly ) + { act->pin -= GNTPIN_hstr_inc; + } else + { act->pin -= GNTPIN_hstw_inc; - - if ( !(act->pin & GNTPIN_hstw_mask) && !readonly ) - gnttab_clear_flag(_GTF_writing, &sha->flags); + if ( !(act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) ) + gnttab_clear_flag(_GTF_writing, &sha->flags); + } if ( !act->pin ) gnttab_clear_flag(_GTF_reading, &sha->flags); + spin_unlock(&rd->grant_table->lock); } @@ -764,8 +752,7 @@ __acquire_grant_for_copy( struct active_grant_entry *act; s16 rc = GNTST_okay; int retries = 0; - u16 sflags; - domid_t sdom; + union grant_combo scombo, prev_scombo, new_scombo; if ( unlikely(gref >= NR_GRANT_ENTRIES) ) PIN_FAIL(error_out, GNTST_bad_gntref, @@ -776,37 +763,43 @@ __acquire_grant_for_copy( spin_lock(&rd->grant_table->lock); - sdom = sha->domid; + /* If already pinned, check the active domid and avoid refcnt overflow. */ + if ( act->pin && + ((act->domid != current->domain->domain_id) || + (act->pin & 0x80808080U) != 0) ) + PIN_FAIL(unlock_out, GNTST_general_error, + "Bad domain (%d != %d), or risk of counter overflow %08x\n", + act->domid, current->domain->domain_id, act->pin); if ( !act->pin || - (!readonly && !(act->pin & GNTPIN_hstw_mask)) ) + (!readonly && !(act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask))) ) { - sflags = sha->flags; + scombo.shorts.flags = sha->flags; + scombo.shorts.domid = sha->domid; for ( ; ; ) { - union grant_combo scombo, prev_scombo, new_scombo; + /* If not already pinned, check the grant domid and type. */ + if ( !act->pin && + (((scombo.shorts.flags & GTF_type_mask) != + GTF_permit_access) || + (scombo.shorts.domid != current->domain->domain_id)) ) + PIN_FAIL(unlock_out, GNTST_general_error, + "Bad flags (%x) or dom (%d). (expected dom %d)\n", + scombo.shorts.flags, scombo.shorts.domid, + current->domain->domain_id); - if ( unlikely((sflags & GTF_type_mask) != GTF_permit_access || - sdom != current->domain->domain_id ) ) - PIN_FAIL(unlock_out, GNTST_general_error, - "Bad flags (%x) or dom (%d). (NB. expected dom %d)\n", - sflags, sdom, current->domain->domain_id); - - /* Merge two 16-bit values into a 32-bit combined update. */ - scombo.shorts.flags = sflags; - scombo.shorts.domid = sdom; - new_scombo = scombo; new_scombo.shorts.flags |= GTF_reading; if ( !readonly ) { new_scombo.shorts.flags |= GTF_writing; - if ( unlikely(sflags & GTF_readonly) ) + if ( unlikely(scombo.shorts.flags & GTF_readonly) ) PIN_FAIL(unlock_out, GNTST_general_error, "Attempt to write-pin a r/o grant entry.\n"); } + prev_scombo.word = cmpxchg((u32 *)&sha->flags, scombo.word, new_scombo.word); if ( likely(prev_scombo.word == scombo.word) ) @@ -815,23 +808,16 @@ __acquire_grant_for_copy( if ( retries++ == 4 ) PIN_FAIL(unlock_out, GNTST_general_error, "Shared grant entry is unstable.\n"); - sflags = prev_scombo.shorts.flags; - sdom = prev_scombo.shorts.flags; + + scombo = prev_scombo; } if ( !act->pin ) { - act->domid = sdom; + act->domid = scombo.shorts.domid; act->frame = gmfn_to_mfn(rd, sha->frame); } } - else if ( unlikely(sdom != current->domain->domain_id) ) - PIN_FAIL(unlock_out, GNTST_general_error, - "Bad domain (%d). (NB. expected dom %d)\n", - sdom, current->domain->domain_id); - else if ( (act->pin & 0x80808080U) != 0 ) - PIN_FAIL(unlock_out, ENOSPC, - "Risk of counter overflow %08x\n", act->pin); act->pin += readonly ? GNTPIN_hstr_inc : GNTPIN_hstw_inc;